package com.cm.biz.db;

import com.cm.kits.YamlKits;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import lombok.extern.slf4j.Slf4j;

import java.sql.Connection;
import java.sql.SQLException;

/**
 * 数据库管理工具
 *
 * @author LWang 2023.02.03
 * @since 1.0.0
 */
@Slf4j
public class Db {
    private final HikariDataSource dataSource;

    public Db() {
        dataSource = new HikariDataSource(YamlKits.load("database.yaml", HikariConfig.class));
    }

    /**
     * 执行 DB 事务性操作
     *
     * @param executor 事务执行对象
     * @param <T>      返回值泛型
     * @return 事务执行结果
     * @throws SQLException 数据库操作异常抛出
     */
    public <T> T execute(IExecutor<T> executor) throws SQLException {
        try (var conn = dataSource.getConnection()) {
            var savePoint = conn.setSavepoint();
            try {
                var result = executor.execute(conn);
                conn.commit();
                return result;
            } catch (SQLException e) {
                conn.rollback(savePoint);
            }
        }
        throw new SQLException("SQL 执行者没有正常运行！");
    }

    /**
     * 执行 DB 查询性操作
     *
     * @param executor 查询执行对象
     * @param <T>      返回值泛型
     * @return 查询结果
     * @throws SQLException 数据库操作异常抛出
     */
    public <T> T query(IExecutor<T> executor) throws SQLException {
        try (var conn = dataSource.getConnection()) {
            return executor.execute(conn);
        }
    }

    public interface IExecutor<T> {
        /**
         * 执行数据库操作
         *
         * @param conn 数据库连接对象
         * @return 执行结果
         * @throws SQLException 数据处理异常抛出
         */
        T execute(Connection conn) throws SQLException;
    }
}
